﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;
using System.Collections.ObjectModel;
using personalplaner.common.utilities;
using System.Windows.Media;
using System.Windows.Controls.Primitives;
using System.Windows.Input;

namespace personalplaner.common.controls
{
    public class ColorPicker : Control
    {
		//Popup _colorPickerCanvasPopup;
        ListBox _availableColors;
        ListBox _standardColors;

        // http://wpftoolkit.codeplex.com/SourceControl/changeset/view/77013#1776193
        static ColorPicker()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ColorPicker), new FrameworkPropertyMetadata(typeof(ColorPicker)));
        }

		public ColorPicker()
		{
			Keyboard.AddKeyDownHandler(this, OnKeyDown);
			Mouse.AddPreviewMouseDownOutsideCapturedElementHandler(this, OnMouseDownOutsideCapturedElement);
		}


    	#region Base Class Overrides

		public override void OnApplyTemplate()
		{
			base.OnApplyTemplate();

			//_colorPickerCanvasPopup = (Popup)GetTemplateChild("PART_ColorPickerPalettePopup");

			_availableColors = (ListBox) GetTemplateChild("PART_AvailableColors");
			if (_availableColors != null)
				_availableColors.SelectionChanged += Color_SelectionChanged;

			_standardColors = (ListBox) GetTemplateChild("PART_StandardColors");
			if (_standardColors != null)
				_standardColors.SelectionChanged += Color_SelectionChanged;
		}

    	private void OnKeyDown(object sender, KeyEventArgs e)
        {
            switch (e.Key)
            {
                case Key.Escape:
                case Key.Tab:
                    {
                        CloseColorPicker();
                        break;
                    }
            }
        }

        private void OnMouseDownOutsideCapturedElement(object sender, MouseButtonEventArgs e)
        {
            CloseColorPicker();
        }

        private void Color_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ListBox lb = (ListBox)sender;

            if (e.AddedItems.Count > 0)
            {
                var colorItem = (ColorItem)e.AddedItems[0];
                SelectedColor = colorItem.Color;
                //UpdateRecentColors(colorItem);
                CloseColorPicker();
                lb.SelectedIndex = -1; //for now I don't care about keeping track of the selected color
            }
        }


        #endregion
		
        #region SelectedColor

        public static readonly DependencyProperty SelectedColorProperty = DependencyProperty.Register("SelectedColor", typeof(Color), typeof(ColorPicker), new FrameworkPropertyMetadata(Colors.Transparent, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnSelectedColorPropertyChanged)));
        public Color SelectedColor
        {
            get { return (Color)GetValue(SelectedColorProperty); }
            set { SetValue(SelectedColorProperty, value); }
        }

        private static void OnSelectedColorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ColorPicker colorPicker = (ColorPicker)d;
            if (colorPicker != null)
                colorPicker.OnSelectedColorChanged((Color)e.OldValue, (Color)e.NewValue);
        }

        private void OnSelectedColorChanged(Color oldValue, Color newValue)
        {
            //SelectedColorText = newValue.GetColorName();

            RoutedPropertyChangedEventArgs<Color> args = new RoutedPropertyChangedEventArgs<Color>(oldValue, newValue);
            args.RoutedEvent = ColorPicker.SelectedColorChangedEvent;
            RaiseEvent(args);
        }

        #endregion //SelectedColor

        private void CloseColorPicker()
        {
            if (IsOpen)
                IsOpen = false;
            ReleaseMouseCapture();
        }

        #region IsOpen

        public static readonly DependencyProperty IsOpenProperty = DependencyProperty.Register("IsOpen", typeof(bool), typeof(ColorPicker), new UIPropertyMetadata(false));
        public bool IsOpen
        {
            get { return (bool)GetValue(IsOpenProperty); }
            set { SetValue(IsOpenProperty, value); }
        }

        #endregion //IsOpen

        #region StandardColors

        public static readonly DependencyProperty StandardColorsProperty = DependencyProperty.Register("StandardColors", typeof(ObservableCollection<ColorItem>), typeof(ColorPicker), new UIPropertyMetadata(CreateStandardColors()));
        public ObservableCollection<ColorItem> StandardColors
        {
            get { return (ObservableCollection<ColorItem>)GetValue(StandardColorsProperty); }
            set { SetValue(StandardColorsProperty, value); }
        }

        #endregion //StandardColors

        #region AvailableColors

        public static readonly DependencyProperty AvailableColorsProperty = DependencyProperty.Register("AvailableColors", typeof(ObservableCollection<ColorItem>), typeof(ColorPicker), new UIPropertyMetadata(CreateAvailableColors()));
        public ObservableCollection<ColorItem> AvailableColors
        {
            get { return (ObservableCollection<ColorItem>)GetValue(AvailableColorsProperty); }
            set { SetValue(AvailableColorsProperty, value); }
        }

        #endregion //AvailableColors

        #region ButtonStyle

        public static readonly DependencyProperty ButtonStyleProperty = DependencyProperty.Register("ButtonStyle", typeof(Style), typeof(ColorPicker));
        public Style ButtonStyle
        {
            get { return (Style)GetValue(ButtonStyleProperty); }
            set { SetValue(ButtonStyleProperty, value); }
        }

        #endregion //ButtonStyle

        private static ObservableCollection<ColorItem> CreateStandardColors()
        {
            var standardColors = new ObservableCollection<ColorItem>();
            standardColors.Add(new ColorItem(Colors.Transparent, "Transparent"));
            standardColors.Add(new ColorItem(Colors.White, "White"));
            standardColors.Add(new ColorItem(Colors.Gray, "Gray"));
            standardColors.Add(new ColorItem(Colors.Black, "Black"));
            standardColors.Add(new ColorItem(Colors.Red, "Red"));
            standardColors.Add(new ColorItem(Colors.Green, "Green"));
            standardColors.Add(new ColorItem(Colors.Blue, "Blue"));
            standardColors.Add(new ColorItem(Colors.Yellow, "Yellow"));
            standardColors.Add(new ColorItem(Colors.Orange, "Orange"));
            standardColors.Add(new ColorItem(Colors.Purple, "Purple"));
            return standardColors;
        }

        private static ObservableCollection<ColorItem> CreateAvailableColors()
        {
            var _standardColors = new ObservableCollection<ColorItem>();

            foreach (var item in ColorUtilities.KnownColors)
            {
                if (!String.Equals(item.Key, "Transparent"))
                {
                    var colorItem = new ColorItem(item.Value, item.Key);
                    if (!_standardColors.Contains(colorItem))
                        _standardColors.Add(colorItem);
                }
            }

            return _standardColors;
        }

        #region Events

        public static readonly RoutedEvent SelectedColorChangedEvent = EventManager.RegisterRoutedEvent("SelectedColorChanged", RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler<Color>), typeof(ColorPicker));
        public event RoutedPropertyChangedEventHandler<Color> SelectedColorChanged
        {
            add { AddHandler(SelectedColorChangedEvent, value); }
            remove { RemoveHandler(SelectedColorChangedEvent, value); }
        }

        #endregion //Events
    }
}
